import G6 from '@antv/g6';
import { NODE } from '../utils/constants';

import { IS_ALIGNMENT_TRUE, IS_ALIGNMENT_FALSE, ADD_UNDO_MANAGER, eventEmitter } from '../utils/event';

//  节点和线active的操作，高亮+菜单
G6.registerBehavior('active', {
  getDefaultCfg() {
    return {
      multiple: false,
      selected: [],
      start: {},
      end: {},
    };
  },
  getEvents() {
    return {
      nodeselectchange: 'onNodesSelectChange',
      'node:dragstart': 'onNodeDragStart',
      'node:dragend': 'onNodeDragEnd',
      'node:click': 'onNodeClick',
      'node:contextmenu': 'onNodeClick', // 右键节点
      'edge:click': 'onEdgeClick',
      'edge:mouseenter': 'onEdgeMouseEnter', // 监听事件 线mousemove，响应函数时 onEdgeMouseEnter
      'edge:mouseleave': 'onEdgeMouseLeave', // 监听事件 线mouseleave，响应函数时 onEdgeMouseLeave
      'edge:contextmenu': 'onEdgeClick', // 右键线
      keydown: 'onKeyDown', //按下键盘
      keyup: 'onKeyUp', //释放键盘
      'canvas:mousedown': 'onCanvasDown', // 点击canvas触发
    };
  },
  onCanvasDragStart(ev) {
    this.removeNodesState();
  },
  onKeyDown(ev) {
    const key = ev.key;
    // Meta->mac的command，Control->windows的ctrl
    if (key === 'Meta' || key === 'Control') {
      this.multiple = true;
    }
  },
  onKeyUp(ev) {
    this.multiple = false;
  },
  onNodesSelectChange({ targets, select }) {
    this.inactiveAll();
    targets.nodes.forEach((node) => {
      this.graph.setItemState(node, 'selected', true);
    });
    //如果被选中的大于1，则将工具栏的可用状态设置为true
    if (this.graph.findAllByState('node', 'selected').length > 1) {
      eventEmitter.emit(IS_ALIGNMENT_TRUE);
    } else {
      eventEmitter.emit(IS_ALIGNMENT_FALSE);
    }
    this.selected = this.graph.findAllByState('node', 'selected');
  },
  onNodeDragStart(ev) {
    if (this.graph._cfg.mode === 'disabled') {
      return;
    }
    this.start = {
      x: ev.x,
      y: ev.y,
    };
  },
  onNodeDragEnd(ev) {
    if (this.graph._cfg.mode === 'disabled') {
      return;
    }
    this.end = {
      x: ev.x,
      y: ev.y,
    };
    const node = ev.item;
    //如果是多选(在选中状态的nodes数量大于1)
    if (this.graph.findAllByState('node', 'selected').length > 1) {
      this.hiddenAllMenu();
    } else {
      //否则，就取消掉其他的节点的selected状态，将当前这个设置为selected
      this.inactiveAll(); //取消其他的节点的选中状态
      this.showNodeMenu(ev); // 展示当前节点的菜单
      this.graph.setItemState(node, 'selected', true); //将当前这个设置为selected
    }

    const start = Object.assign({}, this.start);
    const end = Object.assign({}, this.end);
    const _x = end.x - start.x;
    const _y = end.y - start.y;
    const selecteds = this.graph.findAllByState('node', 'selected').map((node) => {
      const model = node.getModel();
      const it = {};
      it.id = node._cfg.id;
      it.p_x = model.x - _x;
      it.p_y = model.y - _y;
      it.n_x = model.x;
      it.n_y = model.y;
      return it;
    });

    eventEmitter.emit(ADD_UNDO_MANAGER, {
      undo: () => {
        selecteds.forEach((it) => {
          const node = this.graph.findById(it.id);
          const model = node.getModel();
          model.x = it.p_x;
          model.y = it.p_y;
        });

        this.graph.refreshPositions();
      },
      redo: () => {
        selecteds.forEach((it) => {
          const node = this.graph.findById(it.id);
          const model = node.getModel();
          model.x = it.n_x;
          model.y = it.n_y;
        });
        this.graph.refreshPositions();
      },
    });
  },
  onNodeClick(ev) {
    const graph = this.graph;
    const node = ev.item;

    // this 上即可取到配置，如果不允许多个 'active'，先取消其他节点的 'active' 状态
    if (!this.multiple) {
      // this.removeNodesState();
      // 取消掉所有的active节点和线
      this.inactiveAll();
      // 展示node的菜单
      this.showNodeMenu(ev);
      // 置点击的节点状态 'selected' 为 true
      graph.setItemState(node, 'selected', true);

      // 如果是多选
    } else {
      this.hiddenAllMenu();
      // 如果该节点已经是选中状态，则取消掉selected
      if (node.getStates().includes('selected')) {
        graph.setItemState(node, 'selected', false);
        // 否则，置点击的节点状态 'selected' 为 true
      } else {
        graph.setItemState(node, 'selected', true);
      }
    }
    //如果被选中的大于1，则将工具栏的可用状态设置为true
    if (this.graph.findAllByState('node', 'selected').length > 1) {
      eventEmitter.emit(IS_ALIGNMENT_TRUE);
    } else {
      eventEmitter.emit(IS_ALIGNMENT_FALSE);
    }
  },
  onCanvasDown(e) {
    // shouldUpdate 可以由用户复写，返回 true 时取消所有节点的 'active' 状态，即将 'active' 状态置为 false
    if (this.shouldUpdate(e)) {
      this.removeNodesState();
      this.removeEdgesState();
    }
    // 取消掉所有的active节点和线
    this.inactiveAll();
  },
  // 展示节点菜单
  showNodeMenu(ev) {
    const node = ev.item;
    this.nodeConextMenu = ev.currentTarget._nodeMenu;
    const model = node.getModel();
    const { x, y, type } = model;
    this.nodeConextMenu.operaterMenus = document.getElementById('operaterMenus');

    const { width } = node._cfg.keyShape && node._cfg.keyShape._attrs;
    const pos = this.graph.getCanvasByPoint(x, y);
    this.nodeConextMenu.style.display = 'block';
    this.nodeConextMenu.style.left = pos.x + width + 'px';
    this.nodeConextMenu.style.top = pos.y + 'px';
    this.nodeConextMenu.id = model.id;

    if (!this.nodeConextMenu.operaterMenus) {
      return;
    }
    // 如果是start节点，需要隐藏右键菜单中的设置、删除
    if (type === NODE._START) {
      this.nodeConextMenu.operaterMenus.style.display = 'none';
    } else {
      this.nodeConextMenu.operaterMenus.style.display = 'block';
    }
  },
  // 隐藏节点菜单
  hiddenAllMenu() {
    if (this.edgeConextMenu) {
      this.edgeConextMenu.style.display = 'none';
    }
    if (this.nodeConextMenu) {
      this.nodeConextMenu.style.display = 'none';
    }
  },

  onEdgeClick(ev) {
    const graph = this.graph;
    const edge = ev.item;
    // 取消掉所有的active节点和线
    this.inactiveAll();
    const { color } = edge.getModel();
    if (color !== '_BLUE') {
      // 置点击的节点状态 'selected' 为 true
      graph.setItemState(edge, 'selected', true);
    }
    // 展示node的菜单
    this.showEdgeMenu(ev);
  },

  // 展示线菜单
  showEdgeMenu(ev) {
    const model = ev.item.getModel();
    const { startPoint, endPoint, source } = model;
    const sourceNode = this.graph.findById(source);
    const outEdeges = sourceNode.getOutEdges();
    const x = startPoint.x > endPoint.x ? endPoint.x - 35 : endPoint.x;
    const y = endPoint.y / 3 + (2 / 3) * startPoint.y;
    const pos = this.graph.getCanvasByPoint(x, y);
    this.edgeConextMenu = ev.currentTarget._edgeMenu;
    this.edgeConextMenu.setting = this.edgeConextMenu.getElementsByClassName('edgeSetting')[0];
    this.edgeConextMenu.style.display = 'block';
    this.edgeConextMenu.style.left = pos.x + 'px';
    this.edgeConextMenu.style.top = pos.y + 'px';
    this.edgeConextMenu.id = ev.item._cfg.id;
    if (outEdeges.length === 1) {
      this.edgeConextMenu.setting.style.display = 'none';
    } else {
      this.edgeConextMenu.setting.style.display = 'block';
    }
  },
  removeNodesState() {
    this.graph.findAllByState('node', 'selected').forEach((node) => {
      this.graph.setItemState(node, 'selected', false);
    });
  },
  removeEdgesState() {
    this.graph.findAllByState('edge', 'selected').forEach((edge) => {
      this.graph.setItemState(edge, 'selected', false);
      this.graph.setItemState(edge, 'active', false);
    });

    this.graph.findAllByState('edge', 'warning').forEach((edge) => {
      this.graph.setItemState(edge, 'selected', false);
      this.graph.setItemState(edge, 'active', false);
      this.graph.setItemState(edge, 'warning', false);
    });
  },
  inactiveAll() {
    this.hiddenAllMenu();
    this.removeNodesState();
    this.removeEdgesState();
  },

  // 线的onEdgeMouseEnter
  onEdgeMouseEnter(ev) {
    const currentEdge = ev.item;
    this.graph.setItemState(currentEdge, 'compare', false);
    this.graph.setItemState(currentEdge, 'active', true);
  },
  onEdgeMouseLeave(ev) {
    const currentEdge = ev.item;
    const { color } = currentEdge.getModel();
    this.graph.setItemState(currentEdge, 'active', currentEdge.hasState('selected'));
    if (color === '_BLUE') {
      this.graph.setItemState(currentEdge, 'compare', true);
    }
  },
});
